package com.yanqu.road.server.channelserver.manager.activity.washepk;

import com.yanqu.road.dao.impl.activity.area.ChannelWashePkUserDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.area.wase.AreaWashePkConfig;
import com.yanqu.road.entity.activity.area.wase.ChannelWashePkUserData;
import com.yanqu.road.entity.activity.entername.ActivityGroupMatch;
import com.yanqu.road.entity.activity.entername.ChannelFightZone;
import com.yanqu.road.entity.activity.entername.UserEnterName;
import com.yanqu.road.entity.activity.entername.compare.ChannelEnterNameGroupRankSort;
import com.yanqu.road.entity.activity.entername.compare.ChannelEnterNameUserRankSort;
import com.yanqu.road.entity.activity.washe.config.WasheSceneConfig;
import com.yanqu.road.entity.activity.washe.data.WasheSceneData;
import com.yanqu.road.entity.enums.eActivityConfigType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.washe.eWasheSceneType;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.activity.WasheBusiness;
import com.yanqu.road.logic.helper.SeasonHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.cross3.activity.AreaWashePkProto;
import com.yanqu.road.pb.cross3.activity.EnterNameProto;
import com.yanqu.road.pb.cross3.activity.XRankProto;
import com.yanqu.road.server.channelserver.logic.ChannelMessageHelper;
import com.yanqu.road.server.channelserver.manager.activity.ChannelActivityInfoMgr;
import com.yanqu.road.server.channelserver.manager.activity.entername.ChannelEnterNameMgr;
import com.yanqu.road.server.channelserver.manager.activity.entername.ChannelEnterNameRankMgr;
import com.yanqu.road.server.channelserver.manager.activity.entername.EnterNameModel;
import com.yanqu.road.server.channelserver.manager.activity.entername.TempEnterNameActivity;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameMyRankData;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRank;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRankModel;
import com.yanqu.road.server.channelserver.manager.activity.washe.ChannelWasheActivity;
import com.yanqu.road.server.channelserver.manager.activity.washe.ChannelWasheMgr;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelWashPkActivity extends TempEnterNameActivity {

    private final Object addLock = new Object();

    //zoneId,userId
    private Map<Integer, Map<Long, ChannelWashePkUserData>> userDataMap;

    //盘面机制，今日玩法
    private WasheSceneData sceneData;

    private AreaWashePkConfig config;

    public ChannelWashPkActivity(ActivityInfo activityInfo) {
        super(activityInfo);
        setAllAreaRank(true);
        loadConfig();
    }

    public void loadConfig() {
        //时间配置读取
        Map<String, ActivityConfig> activityConfigMap = ChannelActivityInfoMgr.getConfigMap(getActivityInfo().getActivityId());
        AreaWashePkConfig pkConfig = new AreaWashePkConfig();
        pkConfig.setScoreItemId(activityConfigMap.get(eActivityConfigType.AREAFIGHT_SCORE_ITEM_ID.getName()).getIntValue());
        pkConfig.setCartLvList(StringUtils.stringToIntegerList(activityConfigMap.get(eActivityConfigType.AREAFIGHT_CARD_USE_LIMIT.getName()).getValue(), ";"));
        pkConfig.setSceneList(StringUtils.stringToIntegerList(activityConfigMap.get(eActivityConfigType.AREAFIGHT_SCENE.getName()).getValue(), "\\|"));
        config = pkConfig;
    }

    public boolean loadData(){

        Map<Integer, Map<Long, ChannelWashePkUserData>> tempMap = new ConcurrentHashMap<>();

        //加载数据
        Map<Long, ChannelWashePkUserData> tempUserDataMap = new ChannelWashePkUserDataDaoImpl().getChannelWashePkUserData(getActivityInfo().getActivityId());
        for (Map.Entry<Long, ChannelWashePkUserData> entry : tempUserDataMap.entrySet()) {
            ChannelWashePkUserData userData = entry.getValue();
            if(!tempMap.containsKey(userData.getZoneId())){
                tempMap.put(userData.getZoneId(), new ConcurrentHashMap<>());
            }
            tempMap.get(userData.getZoneId()).put(entry.getKey(), entry.getValue());
        }
        userDataMap = tempMap;

        // 盘面机制
        String channelKey = SeasonHelper.getWasheRangeKey(getActivityInfo().getParam6());
        channelKey = channelKey + ";" + getActivityInfo().getActivityId();
        sceneData = WasheBusiness.getWasheSceneData(channelKey);
        if (sceneData == null) {
            WasheSceneData tmpData = new WasheSceneData();
            tmpData.setChannelKey(channelKey);
            tmpData.setSceneList(new ArrayList<>());
            tmpData.setRefreshTime(0);
            tmpData.setInsertOption();
            sceneData = tmpData;
        }
        return true;
    }

    @Override
    public void changeUserValue(long userId, int type, BigInteger value, String param, UserBaseInfo userBaseInfo) {
        //不接受区服上传
    }

    public void changeUserRank(long userId, boolean win){

        //判断下截止时间
        if(!ChannelEnterNameMgr.activityInTime(getActivityInfo())){
            //不在游戏期间，没有榜单
            return;
        }

        ChannelWashePkUserData userData = getChannelUserData(userId, null);

        ActivityGroupMatch match = ChannelEnterNameMgr.getActivityGroupMatch(getActivityInfo().getActivityId(), userId);
        if(match == null) {
            return;
        }

        if(userData.getUserEnterName() == null){
            return;
        }

        int groupId = userData.getUserEnterName().getGroupId();
        if(groupId == 0){
            return;
        }

        //if(win) {
            changeUserRank(userData, match, userData.getUserEnterName());
        //}

        //下发分数成就
        AreaWashePkProto.AreaWashePkUserScoreSync.Builder syncMsg = AreaWashePkProto.AreaWashePkUserScoreSync.newBuilder();
        syncMsg.setUserId(userId);
        syncMsg.setScore(userData.getScore());
        ChannelMessageHelper.sendGamePacket(Protocol.S_AREA_WASHE_PK_DATA_SYNC_FROM_CHANNEL, syncMsg, userData.getUserEnterName().getChannelId(), userData.getUserEnterName().getServerId(), userId);

        //统计分组数据
        BigInteger total = BigInteger.ZERO;
        for (int zoneId : match.getZoneIdList()) {
            Map<Long, ChannelWashePkUserData> map = userDataMap.getOrDefault(zoneId, new HashMap<>());
            for (Map.Entry<Long, ChannelWashePkUserData> entry : map.entrySet()) {
                ChannelWashePkUserData member = entry.getValue();
                total = total.add(BigInteger.valueOf(member.getGroupRankValue()));
            }
        }
        changeGroupRank(userData, match, total);
    }

    @Override
    public EnterNameProto.EnterNameGroupMemberListMsg.Builder getGroupMember(int page, int pageSize, int groupId, int type) {
        EnterNameProto.EnterNameGroupMemberListMsg.Builder msg = EnterNameProto.EnterNameGroupMemberListMsg.newBuilder();
        msg.setPage(page);
        List<ChannelWashePkUserData> list = getUserDataByGroupId(groupId);
        list.sort(new ChannelEnterNameGroupRankSort());
        int start = (page - 1) * pageSize;
        int end = page * pageSize;
        int size = list.size();
        for (int i = start; i < size && i < end; i++) {
            ChannelWashePkUserData userData = list.get(i);
            XRankProto.XUserRankMsg.Builder builder;
            if(userData.getUserBaseInfo() == null){
                continue;
            }
            if(type == getUserConditionType()){
                builder = getUserBuilder(userData);
            }else {
                builder = getUserGroupBuilder(userData);
            }
            msg.addRank(builder);
        }
        return msg;
    }

    @Override
    public void initDataRank() {

        //个人榜单（单局最高积分）
        int rankMax = ChannelActivityInfoMgr.getChannelActivityMaxRank(getActivityInfo().getActivityId(), getUserConditionType());
        //榜单按分组，有多个的
        //key是matchGroupId,zoneId
        Map<Integer, EnterNameRankModel> matchRankModelMap = new ConcurrentHashMap<>();

        //按分配的阵营初始化
        EnterNameModel nameModel = ChannelEnterNameMgr.getEnterNameModel(getActivityInfo().getActivityId());
        if(nameModel != null){
            Map<Integer, ActivityGroupMatch> matchMap = nameModel.getMatchMap();

            //检查分组
            for (Map.Entry<Integer, Map<Long, ChannelWashePkUserData>> entry : userDataMap.entrySet()) {
                for (Map.Entry<Long, ChannelWashePkUserData> dataEntry : entry.getValue().entrySet()) {
                    UserEnterName userEnterName = nameModel.getUserEnterName(dataEntry.getKey());
                    dataEntry.getValue().setUserEnterName(userEnterName);
                }
            }

            //分组个人
            for (Map.Entry<Integer, ActivityGroupMatch> matchEntry : matchMap.entrySet()) {
                ActivityGroupMatch groupMatch = matchEntry.getValue();
                int matchGroupId = groupMatch.getRankMatchGroupId();
                if(matchRankModelMap.containsKey(matchGroupId)){
                    continue;
                }
                EnterNameRankModel userRankModel = new EnterNameRankModel(getActivityInfo().getActivityId(), getUserConditionType(), matchGroupId, rankMax);

                List<Integer> zoneIdList = getMatchGroupZoneList(matchMap, groupMatch);
                LinkedList<ChannelWashePkUserData> list = new LinkedList<>();
                for (Integer zoneId : zoneIdList) {
                    if(userDataMap.containsKey(zoneId)){
                        list.addAll(userDataMap.get(zoneId).values());
                    }
                }

                setUserModelData(rankMax, userRankModel, list);
                matchRankModelMap.put(matchGroupId, userRankModel);
            }

            //地区个人前50
            for (ChannelFightZone zone : nameModel.getZoneList()) {
                if(!userDataMap.containsKey(zone.getAreaId())){
                    continue;
                }
                EnterNameRankModel userRankModel = new EnterNameRankModel(getActivityInfo().getActivityId(), getUserConditionType(), zone.getAreaId(), 37);
                LinkedList<ChannelWashePkUserData> list = new LinkedList<>();
                list.addAll(userDataMap.get(zone.getAreaId()).values());
                setUserModelData(rankMax, userRankModel, list);
                matchRankModelMap.put(zone.getAreaId(), userRankModel);
            }
        }
        if(matchRankModelMap.size() > 0){
            ChannelEnterNameRankMgr.initRank(getActivityInfo().getActivityId(), getUserConditionType(), matchRankModelMap);
        }

        //分组榜单
        initGroupRank(nameModel);
    }

    private void setUserModelData(int rankMax, EnterNameRankModel userRankModel, LinkedList<ChannelWashePkUserData> list) {
        //排序，进行冲榜
        list.sort(new ChannelEnterNameUserRankSort());
        int size = list.size();
        LinkedList<EnterNameRank> rankList = new LinkedList<>();
        for (int i = 0; i < size && i < rankMax; i++) {
            ChannelWashePkUserData userData = list.get(i);
            if(userData.getUserBaseInfo() == null){
                continue;
            }
            if(userData.getUserEnterName() == null){
                continue;
            }
            EnterNameRank nameRank = getEnterNameRank(userData);
            rankList.add(nameRank);
        }
        userRankModel.setRankList(rankList);
    }

    private EnterNameRank getEnterNameRank(ChannelWashePkUserData userData) {
        EnterNameRank nameRank = new EnterNameRank();
        nameRank.setUserId(userData.getUserId());
        nameRank.setChannelId(userData.getUserEnterName().getChannelId());
        nameRank.setGroupId(userData.getUserEnterName().getGroupId());
        nameRank.setZoneId(userData.getUserEnterName().getZoneId());
        nameRank.setValue(BigInteger.valueOf(userData.getUserRankValue()));//最高连胜
        nameRank.setLastUpdateTime(userData.getLastUpdateTime() / 1000);
        nameRank.setUserBaseInfo(userData.getUserBaseInfo());
        nameRank.setParam(String.valueOf(userData.getScore()));
        return nameRank;
    }

    public void initGroupRank(EnterNameModel nameModel){
        if(nameModel == null){
            return;
        }
        Map<Integer, BigInteger> groupValueMap = new HashMap<>();
        Map<Integer, Long> groupUpdateTimeMap = new HashMap<>();
        //按分配的阵营初始化数据
        for (Map.Entry<Integer, ActivityGroupMatch> matchEntry : nameModel.getMatchMap().entrySet()) {
            ActivityGroupMatch groupMatch = matchEntry.getValue();
            LinkedList<ChannelWashePkUserData> list = new LinkedList<>();
            for (Integer zoneId : groupMatch.getZoneIdList()) {
                if(userDataMap.containsKey(zoneId)){
                    list.addAll(userDataMap.get(zoneId).values());
                }
            }
            for (ChannelWashePkUserData userData : list) {
                if (userData.getBadge() <= 0) {
                    continue;
                }
                if(userData.getUserEnterName() == null){
                    continue;
                }
                BigInteger val = groupValueMap.getOrDefault(groupMatch.getGroupId(), BigInteger.ZERO);
                groupValueMap.put(groupMatch.getGroupId(), val.add(BigInteger.valueOf(userData.getGroupRankValue())));
                long updateTime = groupUpdateTimeMap.getOrDefault(groupMatch.getGroupId(), 0L);
                if (updateTime < userData.getLastUpdateTime2()) {
                    groupUpdateTimeMap.put(groupMatch.getGroupId(), userData.getLastUpdateTime2());
                }
            }
        }
        initGroupRankModel(nameModel.getMatchMap(), groupValueMap, groupUpdateTimeMap);
    }

    @Override
    public EnterNameMyRankData getMyRankData(int type, UserEnterName name) {
        EnterNameMyRankData rankData = new EnterNameMyRankData();
        //个人榜单才需要业务数据吧，分组的直接拿榜单
        if(userDataMap.containsKey(name.getZoneId())){
            ChannelWashePkUserData userData = userDataMap.get(name.getZoneId()).get(name.getUserId());
            if(userData != null){
                rankData.setValue(String.valueOf(userData.getUserRankValue()));
                rankData.setParam(String.valueOf(userData.getScore()));
            }
        }
        return rankData;
    }

    /**
     * 玩家数据初始化，由区服变更触发（报名时候，并没有初始化）
     * @param userBaseInfo  首次变更一定要有赋值 定时更新
     */
    public ChannelWashePkUserData getChannelUserData(long userId, UserBaseInfo userBaseInfo){
        UserEnterName userEnterName = ChannelEnterNameMgr.getUserEnterName(getActivityInfo().getActivityId(), userId);
        if(userEnterName == null || userEnterName.getZoneId() == 0){
            return null;
        }
        ChannelWashePkUserData userData;
        synchronized (addLock){
            if(!userDataMap.containsKey(userEnterName.getZoneId())){
                userDataMap.put(userEnterName.getZoneId(), new ConcurrentHashMap<>());
            }
            userData = userDataMap.get(userEnterName.getZoneId()).get(userId);
            if(userData != null){
                if(userBaseInfo != null){
                    userData.setUserBaseInfo(userBaseInfo);
                }
                checkUserEnterName(userId, userBaseInfo, userData);
                return userData;
            }
            userData = new ChannelWashePkUserData();
            userData.setActivityId(getActivityInfo().getActivityId());
            userData.setUserId(userId);
            userData.setZoneId(userEnterName.getZoneId());
            if(userBaseInfo != null) {
                userData.setUserBaseInfo(userBaseInfo);
            }
            userData.setInsertOption();
            userDataMap.get(userEnterName.getZoneId()).put(userId, userData);
        }
        checkUserEnterName(userId, userBaseInfo, userData);
        return userData;
    }

    private void checkUserEnterName(long userId, UserBaseInfo userBaseInfo, ChannelWashePkUserData userData) {
        //拿分组
        UserEnterName userEnterName = ChannelEnterNameMgr.getUserEnterName(getActivityInfo().getActivityId(), userId);
        if(userEnterName != null){
            //cache
            userData.setUserEnterName(userEnterName);
            if(userBaseInfo == null){
                userData.setUserBaseInfo(userEnterName.getUserBaseInfo());
            }else {
                userEnterName.setUserBaseInfo(userBaseInfo);
            }
            userData.setZoneId(userEnterName.getZoneId());
        }
    }

    public void save(){
        if(userDataMap != null){
            for (Map.Entry<Integer, Map<Long, ChannelWashePkUserData>> entry : userDataMap.entrySet()) {
                for (Map.Entry<Long, ChannelWashePkUserData> dataEntry : entry.getValue().entrySet()) {
                    ChannelWashePkUserData userData = dataEntry.getValue();
                    if(userData.isInsertOption()){
                        new ChannelWashePkUserDataDaoImpl().add(userData);
                    }else if(userData.isUpdateOption()){
                        new ChannelWashePkUserDataDaoImpl().update(userData);
                    }
                }
            }
        }
        if(sceneData != null){
            if(sceneData.isInsertOption()){
                WasheBusiness.addWasheSceneData(sceneData);
            }else if(sceneData.isUpdateOption()){
                WasheBusiness.updateWasheSceneData(sceneData);
            }
        }
    }

    public XRankProto.XUserRankMsg.Builder getUserBuilder(ChannelWashePkUserData userData) {
        XRankProto.XUserRankMsg.Builder builder = XRankProto.XUserRankMsg.newBuilder();
        builder.setUserId(userData.getUserId());
        builder.setChannelId(userData.getUserEnterName() != null ? userData.getUserEnterName().getChannelId() : 0);
        builder.setValue(String.valueOf(userData.getUserRankValue()));
        builder.setParam(String.valueOf(userData.getUserRankParam()));
        builder.setExtendParam(String.valueOf(userData.getZoneId()));
        builder.setUpdateTime(userData.getLastUpdateTime() / 1000);
        builder.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userData.getUserBaseInfo()));
        return builder;
    }

    /**
     * 勋章贡献
     */
    public XRankProto.XUserRankMsg.Builder getUserGroupBuilder(ChannelWashePkUserData userData) {
        XRankProto.XUserRankMsg.Builder builder = XRankProto.XUserRankMsg.newBuilder();
        builder.setUserId(userData.getUserId());
        builder.setChannelId(userData.getUserEnterName() != null ? userData.getUserEnterName().getChannelId() : 0);
        builder.setValue(String.valueOf(userData.getGroupRankValue()));
        builder.setParam(String.valueOf(userData.getUserRankValue()));   //也要显示单局最高
        builder.setUpdateTime(userData.getLastUpdateTime2() / 1000);
        builder.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userData.getUserBaseInfo()));
        return builder;
    }

    public List<ChannelWashePkUserData> getUserDataByGroupId(int groupId) {
        List<ChannelWashePkUserData> list = new LinkedList<>();
        EnterNameModel model = ChannelEnterNameMgr.getEnterNameModel(getActivityInfo().getActivityId());
        if(model != null){
            ActivityGroupMatch groupMatch = model.getActivityGroupMatch(groupId);
            if(groupMatch != null){
                for (Integer zoneId : groupMatch.getZoneIdList()) {
                    Map<Long, ChannelWashePkUserData> map = userDataMap.getOrDefault(zoneId, new HashMap<>());
                    list.addAll(new LinkedList<>(map.values()));
                }
            }
        }
        return list;
    }

    // --------------------------- 盘面机制 --------------------------------

    public void checkRefreshScene(boolean force) {
        synchronized (sceneData) {
            long now = System.currentTimeMillis();
            if (!force) {
                if (DateHelper.getZeroTimeStamp(now) <= sceneData.getRefreshTime() && sceneData.getRefreshTime() > 0) {
                    return;
                }
            }
            String channelKey = getActivityInfo().getParam6();
            List<Integer> list = StringUtils.stringToIntegerList(channelKey, ";");
            if (list.size() == 0) {
                return;
            }
            int channelId = list.get(0);
            if(channelId == 0){
                EnterNameModel enterNameModel = ChannelEnterNameMgr.getEnterNameModel(getActivityInfo().getActivityId());
                if(enterNameModel == null){
                    return;
                }
                //拿第一个报名的人
                for (Map.Entry<Long, UserEnterName> nameEntry : enterNameModel.getNameMap().entrySet()) {
                    UserEnterName enterName = nameEntry.getValue();
                    channelId = enterName.getChannelId();
                    break;
                }
                if(channelId == 0) {
                    return;
                }
            }
            ChannelWasheActivity washeActivity = ChannelWasheMgr.getActivity(channelId);
            if (washeActivity == null) {
                return;
            }

            ConcurrentHashMap<Integer, Integer> sceneWeightMap = sceneData.getSceneWeightMap();

            // 拿可选盘面机制和权重
            List<Integer> sceneIdList = new ArrayList<>();
            List<Integer> sceneWeightList = new ArrayList<>();
            for (WasheSceneConfig sceneConfig : washeActivity.getConfig().getSceneConfigMap().values()) {
                if (sceneConfig.isOpen() && eWasheSceneType.getEnumByType(sceneConfig.getSceneId()) != null) {
                    // Id
                    sceneIdList.add(sceneConfig.getSceneId());
                    // Weight
                    sceneWeightList.add(washeActivity.getConfig().getSceneBaseWeight() + sceneWeightMap.getOrDefault(sceneConfig.getSceneId(), 0));
                }
            }

            // 随机
            Random random = new Random();
            List<Integer> randomSceneList = new ArrayList<>();
            for (int i = 0; i < washeActivity.getConfig().getDaySceneNum() && sceneIdList.size() > 0; i++) {
                int index = RandomHelper.getRandomIndexByWeight(sceneWeightList, random);
                int sceneId = sceneIdList.remove(index);
                sceneWeightList.remove(index);
                randomSceneList.add(sceneId);
            }
            if (randomSceneList.isEmpty()) {
                randomSceneList.add(eWasheSceneType.Empty.getType()); // 容错：至少一个盘面机制
            }

            // 设置
            sceneData.setSceneList(randomSceneList);
            sceneData.setRefreshTime(now);

            // 计算下次权重加成
            for (WasheSceneConfig sceneConfig : washeActivity.getConfig().getSceneConfigMap().values()) {
                int sceneId = sceneConfig.getSceneId();
                if (sceneConfig.isOpen() && eWasheSceneType.getEnumByType(sceneId) != null) {
                    if (randomSceneList.contains(sceneId)) {
                        sceneWeightMap.put(sceneId, 0);
                    } else {
                        sceneWeightMap.put(sceneId, sceneWeightMap.getOrDefault(sceneId, 0) + washeActivity.getConfig().getSceneAddiWeight());
                    }
                }
            }
            sceneData.setUpdateOption();
        }
    }

    public AreaWashePkConfig getConfig() {
        return config;
    }

    public WasheSceneData getSceneData() {
        return sceneData;
    }

    public List<Integer> getSceneList(){
        if(sceneData == null){
            return new ArrayList<>();
        }
        return sceneData.getSceneList();
    }

    @Override
    public int getGroupConditionType() {
        return eGamePlayerEventType.WaShePkGroupFightRank.getValue();
    }

    @Override
    public int getAllGroupConditionType() {
        return eGamePlayerEventType.WaShePkAllGroupFightRank.getValue();
    }

    @Override
    public int getUserConditionType() {
        return eGamePlayerEventType.WaShePkUserFightRank.getValue();
    }
}
